
export default class TreeUtil {

  public static foreach<
    K extends string,
    T extends {[k in K]?: T[]}
  >(
    trees: T[],
    key: K,
    back: (tree: T, parents: T[]) => void,
    parents: T[] = []
  ) {
    for (const tree of trees) {
      back(tree, parents);
      const children = tree[key];
      if (children && children.length > 0) {
        TreeUtil.foreach(children, key, back, [...parents, tree]);
      }
    }
  }

  public static toMap<
    K extends string,
    T extends {[k in K]?: T[]},
    R
  >(
    trees: T[],
    key: K,
    getKey: (tree: T, parents: T[]) => string,
    getValue: (tree: T, parents: T[]) => R
  ) {
    const result: Record<string, R> = {};
    TreeUtil.foreach(trees, key, (tree, parents) => {
      const key = getKey(tree, parents);
      const value = getValue(tree, parents);
      result[key] = value;
    });
    return result;
  }

}
